/*
 * @Author: Ma Yuchen
 * @Date: 2022-11-30 19:01:06
 * @LastEditors: Ma YuChen
 * @LastEditTime: 2022-11-30 19:33:29
 * @Description: file content
 * @FilePath: \BootLoader\driverCrc16.c
 */
#include "driverCrc16.h"

static uint16_t Crc_Table[256] = {0};

void InitCRC(void)
{
    int index = 0;
    int bit_cnt = 0;
    uint32_t temp = 0;

    for (index = 0; index < 256; index++)
    {
        temp = 0;
        for (bit_cnt = 8; bit_cnt > 0; bit_cnt--)
        {
            if ((index >> (bit_cnt - 1) ^ temp >> (CRC_WIDTH - 1)) & 0x1)
            {
                temp = (temp << 1) ^ CRC_PLOY;
            }
            else
            {
                temp <<= 1;
            }
        }

        Crc_Table[index] = (uint16_t)temp;
    }
}

uint16_t CalcuCRC(char *buff, int len)
{
    char *tempPtr = buff;
    int reg = CRC_INIT;
    int i = 0;

    for (i = 0; i < len; i++)
    {
        reg = (reg << 8) ^ Crc_Table[((reg >> (CRC_WIDTH - 8)) & 0xFF) ^ *tempPtr];
        tempPtr++;
    }
    return (uint16_t)(reg & 0xFFFF);
}

#define POLY 0x1021
/**
 * Calculating CRC-16 in 'C'
 * @para addr, start of data
 * @para num, length of data
 * @para crc, incoming CRC
 */
uint16_t crc16(unsigned char *addr, int num, uint16_t crc)
{
    int i;
    for (; num > 0; num--) /* Step through bytes in memory */
    {
        crc = crc ^ (*addr++ << 8); /* Fetch byte from memory, XOR into CRC top byte*/
        for (i = 0; i < 8; i++)     /* Prepare to rotate 8 bits */
        {
            crc <<= 1;                        /* just rotate */
            crc ^= (crc & 0x8000) ? POLY : 0; /* rotate and XOR with polynomic */
        }                                     /* Loop for 8 bits */
        crc &= 0xFFFF;                        /* Ensure CRC remains 16-bit value */
    }                                         /* Loop until num=0 */
    return (crc);                             /* Return updated CRC */
}

uint16_t ymodem_crc(unsigned char *buf, int len) { 
    uint16_t crc = 0;
    
    while (len--) {
        crc = crc ^ (*(buf++) << 8);
        for (int i = 0; i < 8; i++) {
            if (crc & 0x8000) 
                crc = (crc << 1) ^ 0x1021;      
            else
                crc = crc << 1;  
        }  
    }

    return crc;
}
